package helper

import (
	"bytes"
	"crypto/tls"
	"encoding/json"
	"encoding/xml"
	"fmt"
	"git.inedcn.com/ined/cmn"
	"git.inedcn.com/ined/cmn/dotenv"
	"github.com/gin-gonic/gin"
	"io/ioutil"
	"net/http"
	"net/url"
	"regexp"
	"rongyy/src/constants"
	"rongyy/src/middlewares"
	"rongyy/src/models"
	"runtime"
	"strings"
)

func Post1(requestXml string) (*models.ResponseXml, error) {
	contentType := "application/soap+xml;charset=UTF-8"
	http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
	_, filename, _, _ := runtime.Caller(0)
	path := strings.Split(filename, "/")
	env := fmt.Sprintf("%s/.env", strings.Join(path[:len(path)-3], "/"))
	dotenv.Load(env)
	resp, err := http.Post(cmn.GetEnv("HIS_URL_V2"), contentType, strings.NewReader(requestXml))
	if err != nil {
		middlewares.Logger.Println("post failed ", err)
		return nil, err
	}

	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		middlewares.Logger.Println("read response body failed", err)
		return nil, err
	}
	middlewares.Logger.Println("read response body failed", string(body))
	result := &models.ResponseXml{}
	err = xml.Unmarshal(body, result)
	if err != nil {
		middlewares.Logger.Println("Unmarshal response body failed", err)
		return nil, err
	}

	return result, nil
}

func Post(requestXml string) (*models.ResponseXml, error) {
	//middlewares.Logger.Println("post xml request==", requestXml)
	contentType := "application/json;charset=UTF-8"
	http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
	_, filename, _, _ := runtime.Caller(0)
	path := strings.Split(filename, "/")
	env := fmt.Sprintf("%s/.env", strings.Join(path[:len(path)-3], "/"))
	dotenv.Load(env)

	reqTransfer := &models.ReqTransfer{
		Str: requestXml,
	}
	data, err := json.Marshal(reqTransfer)
	resp, err := http.Post(cmn.GetEnv("HIS_URL_V2"), contentType, bytes.NewBuffer(data))
	//middlewares.Logger.Println("post failed ", resp)

	if err != nil {
		middlewares.Logger.Println("post failed ", err)
		SaveHisApiLog(requestXml, "", 0, err.Error(), "")
		return nil, err
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		middlewares.Logger.Println("read response body failed", err)
		return nil, err
	}
	res := &models.DataModel{}
	err = json.Unmarshal(body, res)
	bytes, err := json.Marshal(res.Data)
	result := &models.ResponseXml{}
	err = json.Unmarshal(bytes, result)
	if err != nil {
		middlewares.Logger.Println("Unmarshal response body failed2", err)
		return nil, err
	}
	//middlewares.Logger.Println("post xml result===", result)
	SaveHisApiLog(requestXml, string(bytes), 0, "成功", "")
	return result, nil
}

func PostJsonRes(url string, req interface{}) ([]byte, error) {
	middlewares.Logger.Println(req)
	contentType := "application/json;charset=UTF-8"
	http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
	reqTransfer := &models.ReqJsonTransfer{
		Req: req,
	}
	data, err := json.Marshal(reqTransfer)
	if err != nil {
		middlewares.Logger.Println("ERROR PostJson Marshal failed ", err)
		return nil, err
	}
	resp, err := http.Post(url, contentType, bytes.NewBuffer(data))
	if err != nil {
		middlewares.Logger.Println("ERROR PostJson failed ", err)
		return nil, err
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		middlewares.Logger.Println("PostJson ERROR Body failed ", err)
		return nil, err
	}

	res := &models.DataJsonTransferModel{}
	err = json.Unmarshal(body, res)

	return res.Data, nil
}
func PostJson(url string, req interface{}) ([]byte, error) {
	contentType := "application/json;charset=UTF-8"
	http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
	data, err := json.Marshal(req)
	if err != nil {
		middlewares.Logger.Println("ERROR PostJson Marshal failed ", err)
		return nil, err
	}
	resp, err := http.Post(url, contentType, bytes.NewBuffer(data))

	if err != nil {
		//fmt.Println("ERROR PostJson failed ", err)
		return nil, err
	}

	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		middlewares.Logger.Println("PostJson ERROR Body failed ", err)
		return nil, err
	}

	return body, nil
}

func PostXmlJson(url string, xml string) ([]byte, error) {
	contentType := "text/xml;charset=UTF-8"
	http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}

	resp, err := http.Post(url, contentType, bytes.NewBufferString(xml))

	if err != nil {
		//fmt.Println("ERROR PostJson failed ", err)
		return nil, err
	}

	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		middlewares.Logger.Println("PostJson ERROR Body failed ", err)
		return nil, err
	}

	return body, nil
}

func PostHisFeeList(requestXml string) (*models.ResponseFee, error) {
	contentType := "application/json;charset=UTF-8"
	http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
	_, filename, _, _ := runtime.Caller(0)
	path := strings.Split(filename, "/")
	env := fmt.Sprintf("%s/.env", strings.Join(path[:len(path)-3], "/"))
	dotenv.Load(env)

	reqTransfer := &models.ReqTransfer{
		Str: requestXml,
	}
	data, err := json.Marshal(reqTransfer)
	resp, err := http.Post(cmn.GetEnv("HIS_URL_CUS"), contentType, bytes.NewBuffer(data))
	if err != nil {
		middlewares.Logger.Println("post failed ", err)
		return nil, err
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		middlewares.Logger.Println("read response body failed", err)
		return nil, err
	}
	res := &models.DataModel{}
	err = json.Unmarshal(body, res)
	bytes, err := json.Marshal(res.Data)
	result := &models.ResponseFee{}
	err = json.Unmarshal(bytes, result)
	if err != nil {
		middlewares.Logger.Println("Unmarshal response body failed2", err)
		return nil, err
	}

	return result, nil
}

func PostHisFeeList_BACKUP(requestXml string) (*models.ResponseFee, error) {
	contentType := "application/soap+xml;charset=UTF-8"
	http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
	_, filename, _, _ := runtime.Caller(0)
	path := strings.Split(filename, "/")
	env := fmt.Sprintf("%s/.env", strings.Join(path[:len(path)-3], "/"))
	dotenv.Load(env)
	resp, err := http.Post(cmn.GetEnv("HIS_URL_CUS"), contentType, strings.NewReader(requestXml))
	if err != nil {
		middlewares.Logger.Println("post failed ", err)
		return nil, err
	}

	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		middlewares.Logger.Println("read response body failed", err)
		return nil, err
	}
	middlewares.Logger.Println("=======", string(body))
	result := &models.ResponseFee{}
	err = xml.Unmarshal(body, result)
	if err != nil {
		middlewares.Logger.Println("Unmarshal response body failed123123", err)
		return nil, err
	}
	return result, nil
}

func PostHisV3(requestXml string) (*models.ResponseFee, error) {
	contentType := "application/json;charset=UTF-8"
	http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
	_, filename, _, _ := runtime.Caller(0)
	path := strings.Split(filename, "/")
	env := fmt.Sprintf("%s/.env", strings.Join(path[:len(path)-3], "/"))
	dotenv.Load(env)

	reqTransfer := &models.ReqTransfer{
		Str: requestXml,
	}
	data, err := json.Marshal(reqTransfer)
	resp, err := http.Post(cmn.GetEnv("HIS_URL_V3"), contentType, bytes.NewBuffer(data))
	if err != nil {
		middlewares.Logger.Println("post failed ", err)
		return nil, err
	}

	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		middlewares.Logger.Println("read response body failed", err)
		return nil, err
	}
	res := &models.DataModel{}
	err = json.Unmarshal(body, res)
	bytes, err := json.Marshal(res.Data)
	result := &models.ResponseFee{}
	err = json.Unmarshal(bytes, result)
	if err != nil {
		middlewares.Logger.Println("Unmarshal response body failed2", err)
		return nil, err
	}

	return result, nil
}

func PostHisV3_BACKUP(requestXml string) (*models.ResponseFee, error) {
	contentType := "application/soap+xml;charset=UTF-8"
	http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
	_, filename, _, _ := runtime.Caller(0)
	path := strings.Split(filename, "/")
	env := fmt.Sprintf("%s/.env", strings.Join(path[:len(path)-3], "/"))
	dotenv.Load(env)
	resp, err := http.Post(cmn.GetEnv("HIS_URL_V3"), contentType, strings.NewReader(requestXml))
	if err != nil {
		middlewares.Logger.Println("post failed ", err)
		return nil, err
	}

	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		middlewares.Logger.Println("read response body failed", err)
		return nil, err
	}
	result := &models.ResponseFee{}
	err = xml.Unmarshal(body, result)
	if err != nil {
		middlewares.Logger.Println("Unmarshal response body failed123123", err)
		return nil, err
	}
	return result, nil
}

//	func PostTestHis123(requestXml string) (*models.ResponseXml, error) {
//		contentType := "text/soap+xml;charset=UTF-8"
//		resp, err := http.Post("?WSDL=1", contentType, strings.NewReader(requestXml))
//		if err != nil {
//			middlewares.Logger.Println("post failed ", err)
//			return nil, err
//		}
//
//		defer resp.Body.Close()
//		body, err := ioutil.ReadAll(resp.Body)
//		if err != nil {
//			middlewares.Logger.Println("read response body failed", err)
//			return nil, err
//		}
//
//		result := &models.ResponseXml{}
//		err = xml.Unmarshal(body, result)
//		if err != nil {
//			middlewares.Logger.Println("Unmarshal response body failed", err)
//			return nil, err
//		}
//		return result, nil
//	}
func extractIPAddresses(s string) []string {
	// 正则表达式，匹配IPv4地址
	regex := regexp.MustCompile(`(([0-9]{1,3}\.){3}[0-9]{1,3})`)
	// 查找所有匹配项
	matches := regex.FindAllString(s, -1)
	return matches
}

func GetIp(ctx *gin.Context) string {
	ip := ctx.Request.Header.Get("X-Real-IP")
	if ip == "" {
		ip = ctx.Request.Header.Get("X-Forwarded-For")
	}
	if ip == "" {
		ip = extractIPAddresses(ctx.Request.RemoteAddr)[0]
	}
	if ip == "" {
		ip = "127.0.0.1"
	}
	return ip
}

func PostOcr(uri string, image string) ([]byte, error) {
	data := url.Values{"id_card_side": {"front"}, "image": {image}}
	reqBody := strings.NewReader(data.Encode())

	contentType := "application/x-www-form-urlencoded"
	resp, err := http.Post(
		constant.OcrRestUrl+uri,
		contentType,
		reqBody)
	if err != nil {
		middlewares.Logger.Println("ERROR Post failed ", err)
		return nil, err
	}

	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		middlewares.Logger.Println("ERROR Body failed ", err)
		return nil, err
	}

	return body, nil
}

func PostOcrOauth() ([]byte, error) {
	contentType := "application/json;charset=UTF-8"
	resp, err := http.Post(
		fmt.Sprintf("%s&client_id=%s&client_secret=%s",
			constant.OcrOauthUrl,
			constant.OcrClientId,
			constant.OcrClientSecret),
		contentType,
		nil)
	if err != nil {
		middlewares.Logger.Println("ERROR Post failed ", err)
		return nil, err
	}

	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		middlewares.Logger.Println("ERROR Body failed ", err)
		return nil, err
	}

	return body, nil
}

func Get(url string) ([]byte, error) {
	resp, err := http.Get(url)
	if err != nil {
		middlewares.Logger.Println("http get failed", url, err)
		return nil, err
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		middlewares.Logger.Println("http get ReadAll failed", url, err)
		return nil, err
	}
	return body, nil
}

func SaveHisApiLog(req string, resp string, code int, msg string, address string) error {
	hal := &models.HisApiLog{
		JsonInput:  req,
		JsonOutput: resp,
		Address:    address,
		StatusCode: code,
		ErrorMsg:   msg,
	}
	hal.Insert()
	return nil
}
